package nl.nrg3.itunes 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	/**
	 * @author josfaber
	 */
	public class ITunesParser extends EventDispatcher
	{

		private var __tracks : XMLList;
		private var __tracksTotal : int;
		private var __tracksPerThread : int;
		private var __threadTime : int;
		private var __timer : Timer;
		private var __tracksProcessed : int;
		private var __genreDB : Array;
		private var __artistDB : Array;
		private var __albumDB : Array;

		public function ITunesParser( libary : XML, tracksPerThread : int = 100, threadTime : int = 75 )
		{
			__tracksPerThread = tracksPerThread;			__threadTime = threadTime;
			
			__tracks = libary.dict.dict.dict as XMLList; 
			__tracksTotal = __tracks.length( );
		}

		public function parse() : void
		{
			// start parsing tracks in threads
			__tracksProcessed = 0;
			__genreDB = new Array( );			__artistDB = new Array( );			__albumDB = new Array( );
			__timer = new Timer( __threadTime ); 
			__timer.addEventListener( TimerEvent.TIMER, parseThread ); 
			__timer.start( );   
		}

		private function parseThread( e : Event ) : void 
		{ 
			if ( __tracksProcessed < __tracksTotal ) 
			{ 
				for( var i : int = __tracksProcessed; i < __tracksProcessed + __tracksPerThread ; i++ ) 
				{ 
					var track : XML = __tracks[i] as XML; 
					if ( track == null ) 
					{ 
						endParsing( );
						return; 
					} 
					
					// store artists in memory
					var artist : String = getValueFromTrack( track, 'Artist' );
					if ( !inArray( artist, __artistDB ) )
					{
						__artistDB.push( artist );
					}
					
					// store albums in memory
					var album : String = getValueFromTrack( track, 'Album' );
					if ( !inArray( album, __albumDB ) )
					{
						__albumDB.push( album );
					}
					
					// store genres in memory
					var genre : String = getValueFromTrack( track, 'Genre' );
					if ( !inArray( genre, __genreDB ) )
					{
						__genreDB.push( genre );
					}
					
					// next
					__tracksProcessed++; 
				} 
			} 
		}

		private function getValueFromTrack(track : XML, key : String) : *
		{
			var children : XMLList = track.children( );
			var len : int = children.length( );
			for (var i : int = 0; i < len ; i++) 
			{
				if ( children[i].name( ) == 'key' && children[i].text( ) == key && children[i + 1].text( ) != null && children[i + 1].text( ) != '' )
				{
					return typedReturn( children[i + 1].name( ), children[i + 1].text( ) );
				}
			}
			return null;
		}

		private function typedReturn(type : String, value : *) : *
		{
			if ( value == null )
			{
				return null;
			}
			switch( type )
			{
				case 'string':
					return String( value );
					break;
					
				case 'integer':
					return Number( value );
					break;
					
				default:
					return null;
					break;
			}
		}

		private function endParsing() : void
		{
			__timer.reset( );
			dispatchEvent( new ITunesEvent( ITunesEvent.PARSED, false, false, {totalTracks:__tracksTotal, totalArtists:__artistDB.length, totalAlbums:__albumDB.length, totalGenres:__genreDB.length} ) );
		}

		public static function inArray(v : *, a : Array) : Boolean
		{
			var len:int = a.length;
			for (var i : int = 0; i < len ; i++) 
			{
				if (a[i] == v)
					return true;
			}
			return false;
		}

		public function get totalTracks() : int
		{
			return __tracksTotal;
		}

		public function get artists() : Array
		{
			return __artistDB.concat( );
		}

		public function get totalArtists() : int
		{
			return __artistDB.length;
		}

		public function get albums() : Array
		{
			return __albumDB.concat( );
		}

		public function get totalAlbums() : int
		{
			return __albumDB.length;
		}

		public function get genres() : Array
		{
			return __genreDB.concat( );
		}

		public function get totalGenres() : int
		{
			return __genreDB.length;
		}
	}
}
